#include <iostream>
#include <stdio.h>

class Base
{
	public:
		int x;
		int y;

		virtual void function_1()
		{
			printf("function_1...\n");
		}

		virtual void function_2()
		{
			printf("function_2...\n");
		}
};

int main(int argc, char ** argv)
{
	Base base;
	Base *pb;

	pb = &base;

	printf("aaa %ld\n", sizeof(int));		// 4 (64bit)
	printf("aaa %ld\n", sizeof(float));		// 4 (64bit)
	printf("aaa %ld\n", sizeof(long));		// 8 (64bit)
	printf("aaa %ld\n", sizeof(double));	// 8 (64bit)

	printf("size %ld\n", sizeof(class Base));	// 16， 有virtual函数就会多出8字节，多个virtual函数也是8字节。

	pb->function_1();
	pb->function_2();	
}

#if 0

1.当在类里加virtual后多出8个字节，这8个字节在对象的首地址。
2.这8个字节本身是个地址，这个地址里面存的值才是要调用的函数地址。
3.这8个字节指向一个数组，这个数组里面存储的是当前这个对象所有的虚函数的地址。

int main(int argc, char ** argv)
{
    11c9:	f3 0f 1e fa          	endbr64 
    11cd:	55                   	push   %rbp
    11ce:	48 89 e5             	mov    %rsp,%rbp
    11d1:	48 83 ec 40          	sub    $0x40,%rsp
    11d5:	89 7d cc             	mov    %edi,-0x34(%rbp)
    11d8:	48 89 75 c0          	mov    %rsi,-0x40(%rbp)
    11dc:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
    11e3:	00 00 
    11e5:	48 89 45 f8          	mov    %rax,-0x8(%rbp)
    11e9:	31 c0                	xor    %eax,%eax
	Base base;
    11eb:	48 8d 45 e0          	lea    -0x20(%rbp),%rax
    11ef:	48 89 c7             	mov    %rax,%rdi
    11f2:	e8 61 01 00 00       	callq  1358 <_ZN4BaseC1Ev>
	Base *pb;

	pb = &base;
    11f7:	48 8d 45 e0          	lea    -0x20(%rbp),%rax
    11fb:	48 89 45 d8          	mov    %rax,-0x28(%rbp)

	printf("aaa %ld\n", sizeof(int));		// 4 (64bit)
    11ff:	be 04 00 00 00       	mov    $0x4,%esi
    1204:	48 8d 3d 16 0e 00 00 	lea    0xe16(%rip),%rdi        # 2021 <_ZStL19piecewise_construct+0x1d>
    120b:	b8 00 00 00 00       	mov    $0x0,%eax
    1210:	e8 7b fe ff ff       	callq  1090 <printf@plt>
	printf("aaa %ld\n", sizeof(float));		// 4 (64bit)
    1215:	be 04 00 00 00       	mov    $0x4,%esi
    121a:	48 8d 3d 00 0e 00 00 	lea    0xe00(%rip),%rdi        # 2021 <_ZStL19piecewise_construct+0x1d>
    1221:	b8 00 00 00 00       	mov    $0x0,%eax
    1226:	e8 65 fe ff ff       	callq  1090 <printf@plt>
	printf("aaa %ld\n", sizeof(long));		// 8 (64bit)
    122b:	be 08 00 00 00       	mov    $0x8,%esi
    1230:	48 8d 3d ea 0d 00 00 	lea    0xdea(%rip),%rdi        # 2021 <_ZStL19piecewise_construct+0x1d>
    1237:	b8 00 00 00 00       	mov    $0x0,%eax
    123c:	e8 4f fe ff ff       	callq  1090 <printf@plt>
	printf("aaa %ld\n", sizeof(double));	// 8 (64bit)
    1241:	be 08 00 00 00       	mov    $0x8,%esi
    1246:	48 8d 3d d4 0d 00 00 	lea    0xdd4(%rip),%rdi        # 2021 <_ZStL19piecewise_construct+0x1d>
    124d:	b8 00 00 00 00       	mov    $0x0,%eax
    1252:	e8 39 fe ff ff       	callq  1090 <printf@plt>

	printf("size %ld\n", sizeof(class Base));	// 16， 有virtual函数就会多出8字节，多个virtual函数也是8字节。
    1257:	be 10 00 00 00       	mov    $0x10,%esi
    125c:	48 8d 3d c7 0d 00 00 	lea    0xdc7(%rip),%rdi        # 202a <_ZStL19piecewise_construct+0x26>
    1263:	b8 00 00 00 00       	mov    $0x0,%eax
    1268:	e8 23 fe ff ff       	callq  1090 <printf@plt>

	pb->function_1();
    126d:	48 8b 45 d8          	mov    -0x28(%rbp),%rax
    1271:	48 8b 00             	mov    (%rax),%rax
    1274:	48 8b 10             	mov    (%rax),%rdx
    1277:	48 8b 45 d8          	mov    -0x28(%rbp),%rax
    127b:	48 89 c7             	mov    %rax,%rdi
    127e:	ff d2                	callq  *%rdx
	pb->function_2();	
    1280:	48 8b 45 d8          	mov    -0x28(%rbp),%rax
    1284:	48 8b 00             	mov    (%rax),%rax
    1287:	48 83 c0 08          	add    $0x8,%rax
    128b:	48 8b 10             	mov    (%rax),%rdx
    128e:	48 8b 45 d8          	mov    -0x28(%rbp),%rax
    1292:	48 89 c7             	mov    %rax,%rdi
    1295:	ff d2                	callq  *%rdx
}
    1297:	b8 00 00 00 00       	mov    $0x0,%eax
    129c:	48 8b 4d f8          	mov    -0x8(%rbp),%rcx
    12a0:	64 48 33 0c 25 28 00 	xor    %fs:0x28,%rcx
    12a7:	00 00 
    12a9:	74 05                	je     12b0 <main+0xe7>
    12ab:	e8 00 fe ff ff       	callq  10b0 <__stack_chk_fail@plt>
    12b0:	c9                   	leaveq 
    12b1:	c3                   	retq   

#endif
